package com.googlecode.archimedes.filegen.generator.freemarker;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.archimedes.filegen.controller.GenerationException;
import com.googlecode.archimedes.filegen.generator.AbstractGenerator;
import com.googlecode.archimedes.filegen.template.Template;

import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.SimpleHash;
import freemarker.template.TemplateException;

/**
 * <p>
 * Largely this is a Copy of the VelocityGenerator.java
 * The common lines/methods have been noted and should be moved into 
 * a common class. 
 * 
 * This Class generates a single file from a FreeMarker Template
 * </p>
 * 
 * <p>Created: Jan 13, 2005</p>
 * @author John Lema 
 * @version $Id: FreeMarkerGenerator.java 2017 2006-02-17 02:01:34 +0000 (Fri, 17 Feb 2006) jeremyw $
 */
public class FreeMarkerGenerator {

    private static Log log = LogFactory.getLog(FreeMarkerGenerator.class);

    //----- Main Method -----------------------------------------------------------
    protected static void generate(AbstractGenerator generator, String objectName, Template template, SimpleHash dataModel) throws GenerationException {
        try {

            //setup FreeMarker
            Configuration cfg = Configuration.getDefaultConfiguration();
            File templDir = getTemplateDirectory(generator);
            cfg.setDirectoryForTemplateLoading(templDir);

            //locate the template
            freemarker.template.Template currentTemplate = cfg.getTemplate(template.getTemplateName() + ".ftl");
            log.debug("Using a template [" + template.getTemplateName() + ".ftl" + "]");

            //make sure object name is a valid string
            objectName = (objectName == null) ? "" : objectName;
            String outputFileName = template.resolveFileName(new Object[] { objectName}) + template.getExtension();
            String outputPath = generator.getOutputDirectoy() + template.getOutputPath();

            //generate the new content
            StringWriter writer = new StringWriter();
            currentTemplate.process(dataModel, writer);
            String newContent = writer.toString();

            //define the file we want to generate
            log.debug("Generating file [" + outputPath + outputFileName + "].");
            File targetFile = new File(outputPath, outputFileName);
            buildTree(targetFile);

            //read in the old content - leave null
            String oldContent = targetFile.exists() ? FileUtils.readFileToString(targetFile, Charset.defaultCharset().name()) : null;

            //if the oldContent is null (new creation) or the oldContent is different from the new content, write our file.
            if (oldContent == null || !oldContent.equals(newContent)) {
                FileUtils.writeStringToFile(targetFile, newContent, Charset.defaultCharset().name());
            }

        } catch (TemplateException e) {
            log.error("FreeMarkerTemplate : error : Error in the template [" + template.getTemplateName() + "]", e);
            throw new GenerationException(e);
        } catch (ParseException e) {
            log.error("FreeMarkerTemplate : Error Parsing the Template [" + template.getTemplateName() + "]", e);
            throw new GenerationException(e);
        } catch (IOException e) {
            log.error("FreeMarkerTemplate : Syntax error with template [" + template.getTemplateName() + "]", e);
            throw new GenerationException(e);
        } catch (Exception e) {
            throw new GenerationException(e);
        }
    }

    //----- Utility Methods -----------------------------------------------------------

    /**
     * This returns the location of the directory where the freemarker Templates are stored  
     */
    protected static File getTemplateDirectory(AbstractGenerator generator) {
        log.debug("Using the path [" + generator.getResourceDirectory());
        return new File(generator.getResourceDirectory());
    }

    /**
     * This is an Copy of the Same method in  VelocityGenerator - A common parent class should be built
     * There are no differences
     * @see com.tps.filegen.template.Generateable#getProperties()
     */
    protected static void buildTree(File file) {
        //find the parent of the file in question
        File parent = file.getParentFile();

        //create the parent & any directories needed
        parent.mkdirs();
    }
}